/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "serial_command_handler.h"
#include "utils_log.h"
#include "utils_crypto.h"
#include "utils_string_ex.h"
#include "utils_time.h"
#include "peripheral_uart.h"
#include "peripheral_com.h"
#include "common_config_manager.h"
#include <chrono>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <regex>

namespace El {
namespace Protocol {

void SerialCommandHandler::RegisterMethodHandlers(
    std::unordered_map<std::string, std::function<nlohmann::json(const std::string &, const nlohmann::json &)>>
        &handlers)
{
    // 注册获取串口配置方法
    handlers["serial.getConfig"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleSerialGetConfig(id, params);
    };

    // 注册设置串口配置方法
    handlers["serial.setConfig"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleSerialSetConfig(id, params);
    };

    // 注册发送串口数据方法
    handlers["serial.send"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleSerialSend(id, params);
    };
}

nlohmann::json SerialCommandHandler::HandleSerialGetConfig(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理serial.getConfig请求, 参数: {}", params.dump());

    // 检查必要参数
    if (!params.contains("port") || !params["port"].is_string()) {
        EL_ERROR("serial.getConfig请求缺少有效的port参数");
        return CreateErrorResponse(id, -32602, "Invalid params: 'port' is required and must be a string");
    }

    std::string port = params["port"];

    // 验证端口号
    if (!ValidateSerialPort(port)) {
        EL_ERROR("无效的串口端口号: {}", port);
        return CreateErrorResponse(id, -32603, "Invalid serial port: " + port);
    }

    // 如果传入的是完整路径，提取端口名称用作配置键
    std::string portKey = port;
    std::string devicePath = port;

    if (port.find("/dev/") == 0) {
        // 如果是完整路径，提取端口名称
        portKey = port.substr(5); // 去掉 "/dev/" 前缀
        devicePath = port;
    } else {
        // 如果只是端口名称，构建完整路径
        devicePath = "/dev/" + port;
    }

    std::lock_guard<std::mutex> lock(serialMutex_);

    try {
        // 从配置管理器获取串口配置
        auto &configManager = El::Common::ConfigManager::GetInstance();
        std::string configPath = "/uart/" + portKey; // 使用端口名称作为配置键
        auto config = configManager.GetConfig(configPath);

        if (config.is_null()) {
            EL_ERROR("串口配置不存在: {}", portKey);
            return CreateErrorResponse(id, -32603, "Serial port configuration not found: " + portKey);
        }

        // 构建响应结果，使用驼峰命名返回
        nlohmann::json result = {
            {"port", config.value("port", devicePath)}, // 返回完整设备路径
            {"baudRate", config.value("baudRate", 9600)}, {"dataBits", config.value("dataBits", 8)},
            {"stopBits", config.value("stopBits", 1)},    {"parity", config.value("parity", "none")},
            {"enabled", config.value("enabled", false)}};

        EL_DEBUG("获取串口配置成功: {}", result.dump());
        return CreateSuccessResponse(id, result);

    } catch (const std::exception &e) {
        EL_ERROR("获取串口配置时发生异常: {}", e.what());
        return CreateErrorResponse(id, -32603, "Internal error: " + std::string(e.what()));
    }
}

nlohmann::json SerialCommandHandler::HandleSerialSetConfig(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理serial.setConfig请求, 参数: {}", params.dump());

    // 检查必要参数
    if (!params.contains("port") || !params["port"].is_string()) {
        EL_ERROR("serial.setConfig请求缺少有效的port参数");
        return CreateErrorResponse(id, -32602, "Invalid params: 'port' is required and must be a string");
    }

    std::string port = params["port"];

    // 如果传入的是完整路径，提取端口名称用作配置键
    std::string portKey = port;
    std::string devicePath = port;

    if (port.find("/dev/") == 0) {
        // 如果是完整路径，提取端口名称
        portKey = port.substr(5); // 去掉 "/dev/" 前缀
        devicePath = port;
    } else {
        // 如果只是端口名称，构建完整路径
        devicePath = "/dev/" + port;
    }

    // 使用驼峰命名获取参数
    uint32_t baud_rate = params.value("baudRate", 9600);
    uint8_t data_bits = params.value("dataBits", 8);
    uint8_t stop_bits = params.value("stopBits", 1);
    std::string parity = params.value("parity", "none");

    // 验证参数
    if (!ValidateSerialPort(portKey)) {
        EL_ERROR("无效的串口端口号: {}", portKey);
        return CreateErrorResponse(id, -32603, "Invalid serial port: " + portKey);
    }

    if (!ValidateBaudRate(baud_rate)) {
        EL_ERROR("无效的波特率: {}", baud_rate);
        return CreateErrorResponse(id, -32603, "Invalid baud rate: " + std::to_string(baud_rate));
    }

    if (!ValidateSerialParams(data_bits, stop_bits, parity)) {
        EL_ERROR("无效的串口参数: data_bits={}, stop_bits={}, parity={}", data_bits, stop_bits, parity);
        return CreateErrorResponse(id, -32603, "Invalid serial parameters");
    }

    std::lock_guard<std::mutex> lock(serialMutex_);

    auto &uartManager = El::Peripheral::UartManager::GetInstance();

    // 如果串口已初始化，先关闭
    if (uartManager.IsUartInitialized(portKey)) {
        uartManager.DeinitUart(portKey);
    }

    // 初始化串口
    int32_t ret = uartManager.InitUart(portKey, devicePath, true);
    if (ret != 0) {
        EL_ERROR("初始化串口失败: {} -> {}", portKey, devicePath);
        return CreateErrorResponse(id, -32603, "Failed to initialize serial port");
    }

    // 设置串口属性
    El::Peripheral::UART_ATTR attr;
    attr.baudrate = baud_rate;
    attr.databits = data_bits;
    attr.stopbits = (stop_bits == 1) ? El::Peripheral::UART_ONESTOPBIT : El::Peripheral::UART_TWOSTOPBITS;
    attr.parity = ConvertParityFromString(parity);

    ret = uartManager.SetUartAttribute(portKey, attr);
    if (ret != 0) {
        EL_ERROR("设置串口属性失败: {}", portKey);
        return CreateErrorResponse(id, -32603, "Failed to set serial port attributes");
    }

    nlohmann::json result = {{"status", "success"}};

    EL_DEBUG("设置串口配置成功: {}", portKey);
    return CreateSuccessResponse(id, result);
}

nlohmann::json SerialCommandHandler::HandleSerialSend(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理serial.send请求, 参数: {}", params.dump());

    // 检查必要参数
    if (!params.contains("port") || !params["port"].is_string() || !params.contains("data") ||
        !params["data"].is_string()) {
        EL_ERROR("serial.send请求缺少必要参数");
        return CreateErrorResponse(id, -32602, "Invalid params: 'port' and 'data' are required and must be strings");
    }

    std::string port = params["port"];

    // 如果传入的是完整路径，提取端口名称
    std::string portKey = port;
    if (port.find("/dev/") == 0) {
        portKey = port.substr(5); // 去掉 "/dev/" 前缀
    }

    std::string data = params["data"];
    std::string encoding = params.value("encoding", "base64");

    // 验证参数
    if (!ValidateSerialPort(portKey)) {
        EL_ERROR("无效的串口端口号: {}", portKey);
        return CreateErrorResponse(id, -32603, "Invalid serial port: " + portKey);
    }

    if (encoding != "base64" && encoding != "hex" && encoding != "ascii") {
        EL_ERROR("不支持的编码格式: {}", encoding);
        return CreateErrorResponse(id, -32603, "Unsupported encoding: " + encoding);
    }

    std::lock_guard<std::mutex> lock(serialMutex_);

    try {
        // 获取串口管理器
        auto &uartManager = El::Peripheral::UartManager::GetInstance();

        // 检查串口是否已初始化
        if (!uartManager.IsUartInitialized(portKey)) {
            EL_ERROR("串口未初始化: {}", portKey);
            return CreateErrorResponse(id, -32603, "Serial port not initialized: " + portKey);
        }

        // 获取串口Com对象
        auto *com = uartManager.GetUart(portKey);
        if (!com) {
            EL_ERROR("无法获取串口Com对象: {}", portKey);
            return CreateErrorResponse(id, -32603, "Failed to get serial port communication object");
        }

        // 解码数据
        std::vector<uint8_t> binaryData = DecodeData(data, encoding);
        if (binaryData.empty()) {
            EL_ERROR("数据解码失败");
            return CreateErrorResponse(id, -32603, "Failed to decode data");
        }

        // 记录发送时间戳
        auto &timeManager = El::Utils::TimeManager::GetInstance();
        uint64_t currentUtc = timeManager.GetCurrentUtc();
        std::string sendTimestamp = El::Utils::utc64ToString(currentUtc);

        // 发送数据
        int32_t bytesSent = com->Write(binaryData.data(), static_cast<uint32_t>(binaryData.size()));
        if (bytesSent <= 0) {
            EL_ERROR("发送串口数据失败: {}", port);
            return CreateErrorResponse(id, -32603, "Failed to send serial data");
        }

        // 尝试读取响应数据（非阻塞，超时时间短）
        std::vector<uint8_t> responseBuffer(1024);
        std::string responseData;
        uint32_t responseBytes = 0;
        std::string responseTimestamp;

        // 给设备一些时间响应
        std::this_thread::sleep_for(std::chrono::milliseconds(100));

        int32_t bytesReceived = com->ReadLen(responseBuffer.data(), static_cast<uint32_t>(responseBuffer.size()));
        if (bytesReceived > 0) {
            responseBytes = static_cast<uint32_t>(bytesReceived);
            responseBuffer.resize(responseBytes);
            responseData = EncodeToBase64(responseBuffer);
            uint64_t responseUtc = timeManager.GetCurrentUtc();
            responseTimestamp = El::Utils::utc64ToString(responseUtc);
        }

        // 构建响应结果
        nlohmann::json result = {
            {"status", "sent"}, {"bytes_sent", static_cast<uint32_t>(bytesSent)}, {"timestamp", sendTimestamp}};

        if (responseBytes > 0) {
            result["response_data"] = responseData;
            result["response_bytes"] = responseBytes;
            result["response_timestamp"] = responseTimestamp;
        }
        return CreateSuccessResponse(id, result);

    } catch (const std::exception &e) {
        EL_ERROR("发送串口数据时发生异常: {}", e.what());
        return CreateErrorResponse(id, -32603, "Internal error: " + std::string(e.what()));
    }
}

bool SerialCommandHandler::ValidateSerialPort(const std::string &port)
{
    // 验证串口端口号格式（支持完整设备路径和端口名称）
    // 支持格式：
    // - 完整路径：/dev/ttyAMA2, /dev/ttyS0, /dev/ttyUSB0, /dev/COM1 等
    // - 端口名称：COM1, ttyS0, ttyUSB0, ttyAMA0 等
    std::regex portPattern(R"(^(/dev/)?(COM\d+|tty(S|USB|AMA|ACM)\d+|uart\d+)$)");
    return std::regex_match(port, portPattern);
}

bool SerialCommandHandler::ValidateBaudRate(uint32_t baud_rate)
{
    // 支持的波特率列表
    static const std::vector<uint32_t> validBaudRates = {300,   600,   1200,   2400,   4800,   9600,  19200,
                                                         38400, 57600, 115200, 230400, 460800, 921600};

    return std::find(validBaudRates.begin(), validBaudRates.end(), baud_rate) != validBaudRates.end();
}

bool SerialCommandHandler::ValidateSerialParams(uint8_t data_bits, uint8_t stop_bits, const std::string &parity)
{
    // 验证数据位（5-8位）
    if (data_bits < 5 || data_bits > 8) {
        return false;
    }

    // 验证停止位（1或2位）
    if (stop_bits != 1 && stop_bits != 2) {
        return false;
    }

    // 验证校验位
    if (parity != "none" && parity != "odd" && parity != "even" && parity != "mark" && parity != "space") {
        return false;
    }

    return true;
}

uint8_t SerialCommandHandler::ConvertParityFromString(const std::string &parity)
{
    if (parity == "none")
        return El::Peripheral::UART_NOPARITY;
    if (parity == "odd")
        return El::Peripheral::UART_ODDPARITY;
    if (parity == "even")
        return El::Peripheral::UART_EVENPARITY;
    if (parity == "mark")
        return El::Peripheral::UART_MARK;
    if (parity == "space")
        return El::Peripheral::UART_SPACE;
    return El::Peripheral::UART_NOPARITY; // 默认无校验
}

std::string SerialCommandHandler::ConvertParityToString(uint8_t parity)
{
    switch (parity) {
        case El::Peripheral::UART_NOPARITY:
            return "none";
        case El::Peripheral::UART_ODDPARITY:
            return "odd";
        case El::Peripheral::UART_EVENPARITY:
            return "even";
        case El::Peripheral::UART_MARK:
            return "mark";
        case El::Peripheral::UART_SPACE:
            return "space";
        default:
            return "none";
    }
}

std::vector<uint8_t> SerialCommandHandler::DecodeData(const std::string &data, const std::string &encoding)
{
    try {
        if (encoding == "base64") {
            auto decoded = El::Utils::Base64Decode(data);
            return std::vector<uint8_t>(decoded.begin(), decoded.end());
        } else if (encoding == "hex") {
            auto decoded = El::Utils::HexDecode(data);
            return std::vector<uint8_t>(decoded.begin(), decoded.end());
        } else if (encoding == "ascii") {
            return std::vector<uint8_t>(data.begin(), data.end());
        }
    } catch (const std::exception &e) {
        EL_ERROR("数据解码失败: {}", e.what());
    }

    return std::vector<uint8_t>();
}

std::string SerialCommandHandler::EncodeToBase64(const std::vector<uint8_t> &data)
{
    try {
        std::vector<unsigned char> unsignedData(data.begin(), data.end());
        return El::Utils::Base64Encode(unsignedData);
    } catch (const std::exception &e) {
        EL_ERROR("Base64编码失败: {}", e.what());
        return "";
    }
}

} // namespace Protocol
} // namespace El
